package org.hoyi.dispatchs;

import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Parameter;
import java.net.URLDecoder;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import org.apache.commons.lang.StringUtils;
import org.bouncycastle.jce.provider.JDKDSASigner.stdDSA;
import org.hoyi.DB.Interface.IDatabase;
import org.hoyi.DB.comment.DbAttrANNO;
import org.hoyi.DB.conf.HOYIConf;
import org.hoyi.DB.ctrl.Console;
import org.hoyi.cache.CacheRunnable;
import org.hoyi.cache.Cacher;
import org.hoyi.cache.RedisCacheManager;
import org.hoyi.disptachs.model.JsonModel;
import org.hoyi.staticcache.ReqMapInfo;
import org.hoyi.util.HandlerUtil;
import org.hoyi.util.JsonUtil;
import org.hoyi.util.PGUTIL;
import org.hoyi.util.ReflectUtil;
import org.hoyi.util.SessionUtils;
import org.hoyi.util.StrUtil;
import org.hoyi.util.Util;
import org.hoyi.util.RSA.RSAUtils;
import org.hoyi.wb.comment.RequestMode;
import org.hoyi.wb.comment.RequestType;
import org.hoyi.wb.comment.cache.hoyi.HoyiCache;
import org.hoyi.wb.comment.cache.redis.RedisCache;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import net.sf.json.JSONSerializer;

/**
 * Author:ellen Email:ellen@kuaifish.com CreateDate:2015-05-20
 * ModifyDate:2015-06-20 hoyi entities @ hoyi.org 使用请在项目关于内标注hoyi版权，
 * hoyi版权归hoyi.org所有
 */
public abstract class IWebService{
	

	public IWebService(){}

	public static Logger Log = LoggerFactory.getLogger(IWebService.class);
	HttpServletRequest request;
	HttpServletResponse response;
	public String Behavior;
	public boolean Behaviored;
	public IWebService exinstance = null;
	public IDatabase database;
	/**
	 * 请求的类型列表.默认支持GET,安全起见，接口类型的请全部定义为POST.，测试的时候可以用GET
	 */
	public RequestType[] reqtypes = new RequestType[3];
	/**
	 * 当前请求的类型.
	 */
	public RequestType currentReqType;
	/**
	 * 默认支持的Behavion请求类型.
	 */
	public RequestType NormalBehaviorType = RequestType.GET;
	/**
	 * 默认支持的Service请求类型.
	 */
	public RequestType NormalServiceType = RequestType.GET;
	
	/**
	 * 请求的Map信息.
	 */
	public ReqMapInfo reqmapinfo = null;

	private String id;
	
	
	public String getId() {
		return id;
	}

	public void setId(String id) {
		this.id = id;
	}
	/**
	 * 初始化RequeType并且根据Annotation加载客户端定义的RequestType.
	 */
	public void InitAndLoadRequestType() {
		reqtypes[0] = NormalServiceType;
		Annotation[] anos = this.getClass().getAnnotations();
		RequestMode tmp;
		for (Annotation annotation : anos) {
			if (annotation instanceof RequestMode) {
				tmp = (RequestMode) annotation;
				reqtypes = tmp.MODE();
			}
		}
		for (RequestType re : reqtypes) {
			//Console.Info("RE.MODE= " + re);
		}
	}

	/**
	 * 验证请求列表是否有效.
	 * 
	 * @return value
	 */
	public boolean ValidateReq() {
		if(HOYIConf.IGNOREPOSTGET) {
			return true;
		}
		for (RequestType _reqt : reqtypes) {
			if (_reqt != null) {
				if (_reqt.equals(this.currentReqType)) {
					return true;
				}
			}
		}
		return false;
	}
	
	/**
	 * 执行从Mapping 已经缓存的方法.
	 * @param md
	 * @return value
	 */
	public boolean EXESIMREQMETHOD(Method md){
		// 获取md的RequestMode注解，如果请求类型在md的注解内，则通过，否则，返回无权限.
		RequestMode mod = md.getAnnotation(RequestMode.class);
		boolean containerqmode = false;
		boolean modnulls = (mod == null);
		if(!modnulls) {
			for (RequestType tp : mod.MODE()) {
				if(tp.equals(currentReqType)) {
					containerqmode = true;
					break;
				}
			}
		}
	
//		if(!contain) {
//			this.WriteUTF8JSONDATAMSG(-506, "权限不足", null);
//			return true;
//		}
		
		try {
			
			// 只有返回值是void方法才可以执行.
			if(!md.getReturnType().getName().toLowerCase().equals("void")) {
				containerqmode = false;
//				this.WriteUTF8JSONDATAMSG(-506, "内部错误 or 权限不足", null);
//				return true;
			}
			
			// 这里调用，
			// 如果有缓存，则从缓存内拿，而不需要调用方法。
			if(md.isAnnotationPresent(RedisCache.class)) {
				
				// 拿到reids key.查询有无key值，如果没有，则写入redis，然后返回值,否则，直接读取并返回值.
//								new RedisCacheManager().
				
				RedisCache _cache = md.getAnnotation(RedisCache.class);
				
				String ckey = _cache.CachKey() + "_";
				for (String str : _cache.paramkeys()) {
					ckey += str + "_" + this.getParams(str);
				}
				
				RedisCacheManager rediscamanager = new RedisCacheManager();
				String cachedvalues = rediscamanager.GetCahce(ckey);
				if(!StringUtils.isEmpty(cachedvalues)) {
					this.WriteUTF8HTML(cachedvalues);
				}else {
					// 考虑安全问题，必须生命RequestMode的方法才能请求.
					if(md.getParameters().length > 0) {
						if(md.isAnnotationPresent(RequestMode.class) && containerqmode) {
							List<Object> pobjs = new ArrayList<>();
							
							for (Parameter po : md.getParameters()) {
								pobjs.add(this.getParams(po.getName()));
							}
							
							Object cachedValue = md.invoke(this.exinstance, pobjs.toArray());
							rediscamanager.Cache(ckey, cachedValue.toString(), _cache.expiress());
							
							this.WriteUTF8HTML(cachedvalues);
						}else {
							this.WriteUTF8JSONDATAMSG(-506, "内部错误 or 权限不足", null);
							return true;
						}
					}else {
						// 没有REQMode信息，或者包含请求类型，则可以请求.
						if(modnulls || containerqmode) {

							Object cachedValue = md.invoke(this.exinstance, new Object[0]);
							rediscamanager.Cache(ckey, cachedValue.toString(), _cache.expiress());
							
							this.WriteUTF8HTML(cachedvalues);
						}else {
							this.WriteUTF8JSONDATAMSG(-507, "内部错误 or 权限不足", null);
							return true;
						}
					}
				}
			}else {
				// 考虑安全问题，必须生命RequestMode的方法才能请求.
				if(md.getParameters().length > 0) {
					if(md.isAnnotationPresent(RequestMode.class)  && containerqmode) {

						List<Object> pobjs = new ArrayList<>();
						
						for (Parameter po : md.getParameters()) {
							
							pobjs.add(this.getParams(po.getName()));
						}
						
						md.invoke(this.exinstance, pobjs.toArray());
					}else {
						this.WriteUTF8JSONDATAMSG(-506, "内部错误 or 权限不足", null);
						return true;
					}
				}else {
					// 没有REQMode信息，或者包含请求类型，则可以请求.
					if(modnulls || containerqmode) {
						md.invoke(this.exinstance, new Object[0] );	
					} else {
						this.WriteUTF8JSONDATAMSG(-507, "内部错误 or 权限不足", null);
						return true;
					}
				}
			}
			
			this.Behaviored = true;
			return true;
		} catch (Exception e) {
			this.WriteUTF8JSONDATAMSG(-505, "内部错误", null);
			Console.Error(e);
			return true;
		}
	}
	
	public boolean EXESIMBehavior(int plevel){
		Method[] methods =new Method[]{};
		switch (plevel) {
			case 0:
				methods = this.exinstance.getClass().getDeclaredMethods();
				break;
			case 1:

				methods = this.exinstance.getClass().getSuperclass().getDeclaredMethods();
				break;
			case 2:

				methods = this.exinstance.getClass().getSuperclass().getSuperclass().getDeclaredMethods();
				break;
			case 3:

				methods = this.exinstance.getClass().getSuperclass().getSuperclass().getSuperclass().getDeclaredMethods();
				break;
		}
		for (Method md : methods) {
			Console.Info("---------------------------------------------------------11111->" + md.getName());
			if (md.getName().equals(this.Behavior.trim())) {
				try {
					Console.Info("---------------------------------------------------------->" + md.getName());
					
					RequestMode tmpMode;
					RequestType[] reqps = null;
					boolean containannotaion = false;
					for (Annotation ant : md.getAnnotations()) {
						if (ant instanceof RequestMode) {
							reqps = ((RequestMode) ant).MODE();
							containannotaion = true;
						}
					}
					boolean validated = false;
					if(!HOYIConf.IGNOREPOSTGET) {
						if (containannotaion) {
//							System.out.println("contain annotaion");
							for (RequestType requestType : reqps) {
								
								Console.Info("XXXXXXXXXXXXXXXX--->" + requestType.toString() +",currentreqtype:" + currentReqType);
								
								if (requestType.toString().equals(this.currentReqType.toString())) {
									validated = true;
									Console.Info("---------------------------------------------------------->" + md.getName());
									break;
								}
							}
						}else{
//							System.out.println("uncontain annotaion");
							validated = (this.currentReqType.toString().equals(NormalBehaviorType.toString()));
						}
					}else {
						validated = true;
					}

					Class<?> retype = md.getReturnType();
					Console.Info("retTYPE:---------------------------->" + retype.getName());
					// 返回值限制，其他类型的不能请求.
					validated = retype.getName().toLowerCase().equals("void");
					
					if (validated) {
						// 这里调用，
						// 如果有缓存，则从缓存内拿，而不需要调用方法。
						if(md.isAnnotationPresent(RedisCache.class)) {
							// 拿到reids key.查询有无key值，如果没有，则写入redis，然后返回值,否则，直接读取并返回值.
//							new RedisCacheManager().
							
							RedisCache _cache = md.getAnnotation(RedisCache.class);
							
							String ckey = _cache.CachKey() + "_";
							for (String str : _cache.paramkeys()) {
								ckey += str + "_" + this.getParams(str);
							}
							
							RedisCacheManager rediscamanager = new RedisCacheManager();
							String cachedvalues = rediscamanager.GetCahce(ckey);
							if(!StringUtils.isEmpty(cachedvalues)) {
								this.WriteUTF8HTML(cachedvalues);
							}else {
								Object cachedValue = md.invoke(this.exinstance, new Object[0]);
								rediscamanager.Cache(ckey, cachedValue.toString(), _cache.expiress());
								
								this.WriteUTF8HTML(cachedvalues);
							}
//						}else if(md.isAnnotationPresent(HoyiCache.class)){ //返回值 void 跟 缓存值不能为空有冲突，所以暂停此方法.
//							// 拿到reids key.查询有无key值，如果没有，则写入redis，然后返回值,否则，直接读取并返回值.
////							new RedisCacheManager().
//							
//							HoyiCache _cache = md.getAnnotation(HoyiCache.class);
//							
//							String ckey = "HOYI_CACHE_" + _cache.CachKey() + "_";
//							String ids = "";
//							for (String str : _cache.paramkeys()) {
//								ids += str + "_" + this.getParams(str) + "_";
//							}
//							Object execute_instance = exinstance;
//							Object obt = Cacher.Caches(ckey, ids, _cache.expiress(), new CacheRunnable() {
//								@Override
//								public Object GotValue() {
//									Object ret_oo = null;
//									try {
//										ret_oo = md.invoke(execute_instance, new Object[0]);
//									} catch (Exception e) {
//										Console.Error(e);
//									}
//									return ret_oo;
//								}
//							});
//							
//							this.WriteUTF8HTML((String)obt);
						}else {
							md.invoke(this.exinstance, new Object[0]);	
						}
						
						this.Behaviored = true;
						return true;
					}
					
					this.WriteUTF8JSONDATAMSG(-503, "Not Validated Request Type.", null);

					this.Behaviored = true;
					return true;
					
				} catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
 					this.WriteUTF8JSONDATAMSG(-505, "内部错误", null);
					Console.Error(e);
					return true;
				}
			}
		}
		return false;
		
	}

	/**
	 * 执行行为.
	 * 
	 * @return value
	 */
	public boolean ExeBehavior() {
		if(reqmapinfo != null && reqmapinfo.reqmethods != null) {
			EXESIMREQMETHOD(reqmapinfo.reqmethods);
			this.Behaviored = true;
			return true;
		}else {
			this.Behavior = getParams("behavior");
			if ((this.Behavior != null) && (this.Behavior.trim().length() > 0)) {
				Console.Info("EXINSTANCE:" + this.exinstance);
				boolean executed = false;
				for(int i = 0; i < 4; i ++){
					executed = EXESIMBehavior(i);
					if(executed){
						this.Behaviored = true;
						return true;
					}
				}
			}
			this.Behaviored = false;
			return false;
		}
	}

	/**
	 * 从请求中获取数据.
	 * 
	 * @param t
	 * @return value
	 */
	public <T> T getModelFromReq(Class<T> t) {
		try {
			Object xT = null;
			xT = t.newInstance();

			Field[] fields = xT.getClass().getDeclaredFields();

			for (Field field : fields) {
				if (field.isAnnotationPresent(DbAttrANNO.class)) {
					DbAttrANNO anno = (DbAttrANNO) field.getAnnotation(DbAttrANNO.class);
					try {
						String medname = "set" + Util.FirstUpToParscal(anno.FieldName());
						if (ReflectUtil.ContainMethod(xT.getClass().getMethods(), medname)) {
							Method med = xT.getClass().getDeclaredMethod(medname, new Class[] { String.class });
							if (med != null) {
								med.invoke(xT, new Object[] { getParams(anno.FieldName()) });
							}
						}
					} catch (Exception e) {
						Console.Error(e);
					}
					anno.FieldName();
				}
			}
			return (T) xT;
		} catch (Exception e) {
			Console.Error(e);
		}
		return null;
	}
	
	/**
	 * 接收网页参数封装实体
	 */
	public <T> T getModel(Class<T> clazz) {
		try {
			Object model = null;
			model = clazz.newInstance();

			Method[] methods1 = clazz.getMethods();
			for (Method method1 : methods1) {
				String name = method1.getName();
				if (name.startsWith("set")) {
					String substring = name.substring(3);
					if (!Character.isLowerCase(substring.charAt(0))) {
						String s = (new StringBuilder()).append(Character.toLowerCase(substring.charAt(0))).append(substring.substring(1)).toString();
						String params = this.getParams(s);
						boolean containkey = this.getRequest().getQueryString().contains(s);
						if(containkey) {
							method1.invoke(model, params);
						}
					}
				}
			}
			return (T) model;
		} catch (Exception e) {
			e.printStackTrace();
		}
		return null;
	}

	public int GetParamsInt(String key, int defvalue) {
		String params = getParams(key);
		if(params == null || params == "") {
			return defvalue;
		}
		return Integer.parseInt(params);
	}
	public int GetParamsInt(String key) {
		return Integer.parseInt(getParams(key));
	}
	
	/**
	 * 获取参数方法，默认全部用URLDecode解密。
	 * 不想解密的请传参数，false
	 * @param key
	 * @return value
	 */
	public String getParams(String key) {
		return this.getParams(key, true, true);
	}

	public String getParams(String key, boolean urldecode) {
		return getParams(key, urldecode, true);
	}
	/**
	 * 
	 * 获取参数方法，默认全部用URLDecode解密。
	 * 不想解密的请传参数，false
	 * 
	 * @param key
	 * @param urldecode
	 * @return value
	 */
	public String getParams(String key, boolean urldecode, boolean ejs) {
		//设置编码方式为UTF-8
		try
		{
			this.request.setCharacterEncoding("UTF-8");
		}
		catch (UnsupportedEncodingException e)
		{
			Console.Error(e);
		}
		String val = this.request.getParameter(key);
//		if (val != null && val.equals("undefined")) {
//			val = null;
//		}
		if(urldecode){
			if(val != null && val != "" && val.length() > 0){
				try {// 默认所有的方法，都用URLDecoder.Decode解密.
					val = URLDecoder.decode(val, "utf-8");
				} catch (UnsupportedEncodingException e) {
					Console.Error("获取URLDECODE.Params错误,key:" + key + " -> " + e.getMessage());
				}
			}
		}
		if (null != val){
			if(ejs){
				return val.replace("<script>", "＜script＞").replace("</script>", "＜/script＞").replace("<script", "＜script").replace("\\", "＼").replace("%", "&#37;");//防js注入
			}
			return val;
		}
		return "";
	}
	/**
	 * 获取并解密参数.RSA加密不能与URLDECODE加密同时使用.
	 * @param key
	 * @return value
	 */
	public String getRSAParams(String key){
		String param = this.getParams(key);
		RSAUtils rsa = new RSAUtils();
		try {
			param = rsa.decrypttoStr(HOYIConf.HRSAPrivateKey, param);
			if (null != param)
				return param.replace("<script>", "＜script＞").replace("</script>", "＜/script＞").replace("<script", "＜script").replace("\\", "＼").replace("%", "&#37;");//防js注入
		} catch (Exception e) {
			Console.Error(e);
		}
		return param;
	}

	public String getStartid() {
		return this.getParams("startid");
	}

	public int getoffset() {
		String offset = getParams("offset");
		try {
			return Integer.parseInt(offset);
		} catch (Exception e) {
			Console.Error(e);
		}
		return 10;
	}
	
	/**
	 * 先getParams("pgindex")
	 * 为空，则复制1
	 * @return value
	 */
	public int getpgindex() {
		String pgindex = getParams("pgindex");
		if (StringUtils.isNotBlank(pgindex)) {
			try {
				return Integer.parseInt(pgindex);
			} catch (Exception e) {
				Console.Error("getpgindex:" + e);
			}
		}
		return 1;
	}
	/**
	 * 先getParams("pagesize")
	 * 为空，则复制10
	 * @return value
	 */
	public int getpagesize() {
		String pagesize = getParams("pagesize");
		try {
			return Integer.parseInt(pagesize);
		} catch (Exception e) {
			Console.Error(e);
		}
		return 10;
	}

	public Map<String, Object> getPagingMap() {
		int pgindex = getpgindex();
		int pagesize = getpagesize();
		String filter = getParams("FILTER");

		Map maps = new HashMap();
		maps.put("offset", Integer.valueOf(pgindex * pagesize));
		maps.put("pagesize", Integer.valueOf(pagesize));
		maps.put("filters", filter);

		return maps;
	}

	public int CalcPgs(int datacount) {
		int pagesize = getpagesize();
		int pagecount = datacount / pagesize;
		if (datacount % pagesize > 0) {
			pagecount++;
		}
		return pagecount;
	}

	public String getPgs(int datacount, int pgindex, String methodname) {
		int pagecount = CalcPgs(datacount);
		return PGUTIL.I().GETNAVIHTML(this.request, pagecount, pgindex, methodname);
	}

	public String getPgs(int datacount, String methodname) {
		int pagecount = CalcPgs(datacount);
		int pgindex = getpgindex();
		return PGUTIL.I().GETNAVIHTML(this.request, pagecount, pgindex, methodname);
	}

	public String getPgs(int datacount, String methodname, String params) {
		int pagecount = CalcPgs(datacount);
		int pgindex = getpgindex();
		return PGUTIL.I().GETNAVIHTML(this.request, pagecount, pgindex, methodname, params);
	}

	public HttpServletRequest getRequest() {
		return this.request;
	}

	public void setRequest(HttpServletRequest request) {
		this.request = request;
	}

	public HttpServletResponse getResponse() {
		return this.response;
	}

	public void setResponse(HttpServletResponse response) {
		this.response = response;
	}

	void Write(String content, String contenttype) {
		try {
			//Console.Info("response:" + this.response);
//			System.out.println("response:" + this.response);
			responseUtil.getinstance().Write(this.response, content, contenttype);
		} catch (IOException e) {
			Console.Error(e);
		}
	}
	
	public String getLoginedUserid(){
		return SessionUtils.get_Logined_USERID(getRequest());
	}

	public String getUserid() {
		return this.request.getParameter("userid");
	}

	public String getTokenId() {
		return this.request.getParameter("tokenid");
	}

	public void WriteUTF8Text(String content) {
		Write(content, "text/plain; charset=UTF-8");
	}
	/**
	 * 输出HTML.
	 * @param content
	 */
	public void WriteUTF8HTML(String content) {
		Write(content, "text/html; charset=UTF-8");
	}
	
	public void WriteUTF8JSON(String content) {
		Write(content, "text/json; charset=UTF-8");
	}
	/**
	 * 输出alert('alertmsg');
	 * @param alertmsg
	 */
	public void Alert(String alertmsg) {
		WriteUTF8HTML("alert('" + alertmsg + "');");
	}
	/**
	 * 输出alert('alertmsg');
	 * 然后再输出 attscript;
	 * @param alertmsg
	 */
	public void Alert(String alertmsg, String attscript) {
		WriteUTF8HTML("alert('" + alertmsg + "');" + attscript);
	}
	/**
	 * 输出 js
	 * @param jscript
	 */
	public void WRITEJS(String jscript) {
		WriteUTF8HTML(jscript);
	}
	
	/**
	 * 写入Session.
	 * @param key
	 * @param values
	 */
	public void SetSession(String key, String values){
		HttpSession httpSession = getRequest().getSession(true);
		httpSession.setAttribute(key, values);
	}
	/**
	 * 删除Session.
	 * @param key
	 */
	public void DeleteSession(String key) {
		HttpSession httpSession = getRequest().getSession(true);
		httpSession.removeAttribute(key);
	}
	/**
	 * 获取Session内的值.
	 * @param key
	 * @return value
	 */
	public String GetSession(String key) {
		Object usid = getRequest().getSession(true).getAttribute(key);
		if (usid == null) {
			return null;
		}
		return usid.toString();
	}
	/**
	 * 设置Cookies.
	 * @param key
	 * @param values
	 * @param expiresstime 过期时间.
	 */
	public void SetCookies(String key, String values, int expiresstime) { 
		Cookie keyCookie = new Cookie(key, values);
		keyCookie.setMaxAge(expiresstime);
		keyCookie.setPath("/");
		//keyCookie.setPath(getRequest().getContextPath() + "/getcookies.sxt");
		getResponse().addCookie(keyCookie);
	}
	/**
	 * 删除Cookies.
	 * @param key
	 */
	public void DeleteCookies(String key) {
		 Cookie[] cookies = getRequest().getCookies();  
         if (null==cookies) {  
           //  System.out.println("没有cookie==============");  
         } else {  
             for(Cookie cookie : cookies){  
                 if(cookie.getName().equals(key)){  
                     cookie.setValue(null);  
                     cookie.setMaxAge(0);// 立即销毁cookie  
                     cookie.setPath("/");  
                     //System.out.println("被删除的cookie名字为:"+cookie.getName());  
                     getResponse().addCookie(cookie);  
                     break;  
                 }  
             }  
         }  
	}
	/**
	 * 计算Limit 并带上Limit
	 * @param pgidx
	 * @param PgCount
	 * @param pgsize
	 * @return
	 */
	public String CalcLimit_ADLIMIT(int pgidx, int PgCount, int pgsize) {
		return " limit " + CalcLimit(pgidx, PgCount, pgsize);
	}
	
	/**
	 * 计算Limit.
	 * @param pgidx 页码
	 * @param PgCount 总页数
	 * @param pgsize 一页条数
	 * @return
	 */
	public String CalcLimit(int pgidx, int PgCount, int pgsize) {
		if (pgidx <= 0)
			pgidx = 1;
		String limit = "";
		if (pgsize > 0 && PgCount > 0) {
			if (pgidx <= PgCount) {
				limit = ((pgidx - 1) * pgsize) + "," + pgsize;
			} else if (pgidx > PgCount) {
				pgidx = PgCount;
				limit = ((PgCount - 1) * pgsize) + "," + pgsize;
			}
		} else {
			limit = "0," + pgsize;
		}
		return limit;
	}
	
	/**
	 * 计算PageCount.
	 * @param pgsize
	 * @param dtcount
	 * @return
	 */
	public int CalcPageSize(int pgsize, int dtcount) {
		int PgCount = 0;
		if (pgsize > 0) {
			PgCount = (dtcount / pgsize) + ((dtcount % pgsize) > 0 ? 1 : 0);
		}
		return PgCount;
	}
	/**
	 * 计算总页数，和页码,
	 * @param _datacount
	 * @param _pagesize
	 * @param _pgidx
	 * @return List<Integer> 第一个 pgcount, 第二个 pageindex, 第二个可能没有.
	 */
	public List<Integer> CalcPageCount(int _datacount, int _pagesize, int _pgidx) {
		List<Integer> idx = new ArrayList<Integer>();
		if (_datacount > 0) {
			int pgcount = _datacount / _pagesize;
			if (_datacount % _pagesize > 0) {
				pgcount++;
			}
			idx.add(0, pgcount);
//			setPageCount(pgcount);
			if (_pgidx > pgcount) {
				idx.add(1, pgcount);
			}
//				setPageIndex(getPageCount());
		} else {
			idx.add(0, 0);
//			setPageCount(0);
		}
		return idx;
	}
	
	/**
	 * 根据KEY获取Cookies.
	 * @param key
	 * @return value
	 */
	public String GetCookies(String key) {
		Cookie[] cookies = getRequest().getCookies();
		if (cookies!=null) {
			for (Cookie cookie : cookies) {
				if (cookie.getName().equals(key)) {
					Object v = cookie.getValue();
					if(v != null) {
						return v.toString();
					}
				}
				
			}	
		}
		return "";
	}
	
	public JsonModel SendRedirect(String url) {
		JsonModel retmodel = new JsonModel();
		try {
			getResponse().sendRedirect(url);
			retmodel.setStatus(202);
		} catch (IOException e) {
			retmodel.setStatus(404);
			retmodel.setMsg(e.getMessage());
		}
		return retmodel;
	}
	/**
	 * 前端页面跳转,用的是WriteUTF8HTML.
	 * @param url
	 */
	public void LocationHref(String url) {
		WriteUTF8HTML("window.location.href='"+ url+"'");
	}
	/**
	 * 这里直接输出JS.
	 * @param content
	 */
	public void WriteUTF8JavaScript(String content) {
		Write("<script type=\"text/javascript\">" + content + "</script>", "text/html; charset=UTF-8");
	}
	
	public void WriteUTF8XML(String content)
	{
		Write(content, "text/xml; charset=UTF-8");
	}

	public void WriteUTF8JSON(JsonModel jsonModel) {
		Write(JSONSerializer.toJSON(jsonModel, JsonUtil.Config).toString(), "text/json; charset=UTF-8");
	}

	public void WriteUTF8JSONDATA(Object data) {
		JsonModel json = new JsonModel(1, "");
		json.setData(data);
		Write(JSONSerializer.toJSON(json, JsonUtil.Config).toString(), "text/json; charset=UTF-8");
	}

	public void WriteUTF8JSONDATAMSG(String msg, Object data) {
		JsonModel json = new JsonModel(1, msg);
		json.setData(data);
		Write(JSONSerializer.toJSON(json, JsonUtil.Config).toString(), "text/json; charset=UTF-8");
	}

	public void WriteUTF8JSONDATAMSG(int result, String msg, Object data) {
		JsonModel json = new JsonModel(result, msg);
		json.setData(data);
		Write(JSONSerializer.toJSON(json, JsonUtil.Config).toString(), "text/json; charset=UTF-8");
	}

	public void HandlerEx(String HandlerType, int ret) {
		try {
			HandlerUtil.HandlerEx(getResponse(), HandlerType, ret);
			return;
		} catch (IOException e) {
			Console.Error(e);
		}
	}
	
}
